]> dgit.raspbian.org Git - gnome-shell.git/commitdiff
StWidget: don't forget to invalidate the paint state if not on stage
authorCosimo Cecchi <cosimo@endlessm.com>
Wed, 21 Nov 2018 02:25:51 +0000 (18:25 -0800)
committerCosimo Cecchi <cosimo.cecchi@gmail.com>
Tue, 4 Dec 2018 15:52:36 +0000 (15:52 +0000)
If the actor is not on the stage yet (i.e. does not have a theme
node), but has a paint state cached, we currently fail to invalidate
it, which will lead to the actor painting with old contents once it
gets onto the stage.

This commit fixes the issue by changing our invalidation strategy;
previously we were looking at the widget's own theme node to determine
if it should be invalidated or not.
Now we look at the theme nodes of our cached paint states. When the
widget is mapped on stage, those are the same as the widget's own
theme node, but when the widget is not on the stage, we'll still be
able to invalidate them.

As part of this, we move the invalidation API to StThemeNodePaintState,
which is a more natural place for our use case.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/314

src/st/st-theme-node-drawing.c
src/st/st-theme-node.h
src/st/st-widget.c

index f59065aefb9a4c025c6e92f6e11001272958cc6a..9f7e6b6ca4a4cbfcbcc462e2001ad0489c0e6b5a 100644 (file)
@@ -1414,6 +1414,32 @@ st_theme_node_load_background_image (StThemeNode *node)
   return node->background_texture != COGL_INVALID_HANDLE;
 }
 
+static gboolean
+st_theme_node_invalidate_resources_for_file (StThemeNode *node,
+                                             GFile       *file)
+{
+  StBorderImage *border_image;
+  gboolean changed = FALSE;
+  GFile *theme_file;
+
+  theme_file = st_theme_node_get_background_image (node);
+  if ((theme_file != NULL) && g_file_equal (theme_file, file))
+    {
+      st_theme_node_invalidate_background_image (node);
+      changed = TRUE;
+    }
+
+  border_image = st_theme_node_get_border_image (node);
+  theme_file = border_image ? st_border_image_get_file (border_image) : NULL;
+  if ((theme_file != NULL) && g_file_equal (theme_file, file))
+    {
+      st_theme_node_invalidate_border_image (node);
+      changed = TRUE;
+    }
+
+  return changed;
+}
+
 static void st_theme_node_prerender_shadow (StThemeNodePaintState *state);
 
 static void
@@ -2753,3 +2779,17 @@ st_theme_node_paint_state_invalidate (StThemeNodePaintState *state)
   state->alloc_width = 0;
   state->alloc_height = 0;
 }
+
+gboolean
+st_theme_node_paint_state_invalidate_for_file (StThemeNodePaintState *state,
+                                               GFile                 *file)
+{
+  if (state->node != NULL &&
+      st_theme_node_invalidate_resources_for_file (state->node, file))
+    {
+      st_theme_node_paint_state_invalidate (state);
+      return TRUE;
+    }
+
+  return FALSE;
+}
index e71c1d5227277d36dfd97c6535becf96a396dbe9..1b43c9afe67bfbed317deb46e5959f1214304d7c 100644 (file)
@@ -291,6 +291,9 @@ void st_theme_node_paint_state_free (StThemeNodePaintState *state);
 void st_theme_node_paint_state_copy (StThemeNodePaintState *state,
                                      StThemeNodePaintState *other);
 void st_theme_node_paint_state_invalidate (StThemeNodePaintState *state);
+gboolean st_theme_node_paint_state_invalidate_for_file (StThemeNodePaintState *state,
+                                                        GFile                 *file);
+
 void st_theme_node_paint_state_set_node (StThemeNodePaintState *state,
                                          StThemeNode           *node);
 
index db984ac9bb350df804a90910c94dbd70e4efa9c4..7c39b358552bcecd31070d71ca4b5b287fa7cddf 100644 (file)
@@ -289,44 +289,17 @@ st_widget_texture_cache_changed (StTextureCache *cache,
 {
   StWidget *actor = ST_WIDGET (user_data);
   StWidgetPrivate *priv = st_widget_get_instance_private (actor);
-  StThemeNode *node = priv->theme_node;
-  StBorderImage *border_image;
   gboolean changed = FALSE;
-  GFile *theme_file;
-
-  if (node == NULL)
-    return;
-
-  theme_file = st_theme_node_get_background_image (node);
-  if ((theme_file != NULL) && g_file_equal (theme_file, file))
-    {
-      st_theme_node_invalidate_background_image (node);
-      changed = TRUE;
-    }
+  int i;
 
-  border_image = st_theme_node_get_border_image (node);
-  theme_file = border_image ? st_border_image_get_file (border_image) : NULL;
-  if ((theme_file != NULL) && g_file_equal (theme_file, file))
+  for (i = 0; i < G_N_ELEMENTS (priv->paint_states); i++)
     {
-      st_theme_node_invalidate_border_image (node);
-      changed = TRUE;
+      StThemeNodePaintState *paint_state = &priv->paint_states[i];
+      changed |= st_theme_node_paint_state_invalidate_for_file (paint_state, file);
     }
 
-  if (changed)
-    {
-      /* If we prerender the background / border, we need to update
-       * the paint state. We should probably implement a method to
-       * the theme node to determine this, but for now, just wipe
-       * the entire paint state.
-       *
-       * Use the existing state instead of a new one because it's
-       * assumed the rest of the state will stay the same.
-       */
-      st_theme_node_paint_state_invalidate (current_paint_state (actor));
-
-      if (clutter_actor_is_mapped (CLUTTER_ACTOR (actor)))
-        clutter_actor_queue_redraw (CLUTTER_ACTOR (actor));
-    }
+  if (changed && clutter_actor_is_mapped (CLUTTER_ACTOR (actor)))
+    clutter_actor_queue_redraw (CLUTTER_ACTOR (actor));
 }
 
 static void